/*****************************************************************************
 * http_proxy.go
 * Names: 张奕鸣
 * NetIds:10235101501
 *****************************************************************************/

// TODO: implement an HTTP proxy
package main

import (
	"fmt"
	"io"
	"net"
	"net/http"
	"os"
	"strings"
)

func handleRequest(clientConn net.Conn) {
	defer clientConn.Close()

	// 读取HTTP请求
	buffer := make([]byte, 4096)
	n, err := clientConn.Read(buffer)
	if err != nil {
		fmt.Println("Error reading from client:", err)
		return
	}
	request := string(buffer[:n])

	// 解析HTTP请求
	// fmt.Println(request)

	requestURI := ""
	requestMethod := ""

	if idx := strings.Index(request, "GET"); idx != -1 {
		requestMethod = "GET"
		requestURI = strings.TrimSpace(strings.Split(request, " ")[1])
	} else {
		// 不是GET请求，返回500 Internal Error
		io.WriteString(clientConn, fmt.Sprintf("500 Internal Error"))
		return
	}

	// 处理GET请求
	if requestMethod == "GET" {
		req, err := http.NewRequest("GET", requestURI, nil)
		if err != nil {
			fmt.Println("Error creating request:", err)
			return
		}
		// clientReader := bufio.NewReader(clientConn)
		// req, err := http.ReadRequest(clientReader)
		// if err != nil || req.Method != "GET" {
		// 	io.WriteString(clientConn, fmt.Sprintf("500 Internal Error"))
		// 	return
		// }
		// 添加或修改头部
		// req.Header.Set("Host", requestURI)

		host := req.Host
		targetConn, err := net.Dial("tcp", host+":80")

		if err != nil {
			io.WriteString(clientConn, fmt.Sprintf("500 Internal Error"))
			return
		}

		defer targetConn.Close()

		req.Header.Set("Connection", "close")
		err = req.Write(targetConn)
		if err != nil {
			io.WriteString(clientConn, fmt.Sprintf("500 Internal Error"))
			return
		}
		io.Copy(clientConn, targetConn)

		//使用do的方法会自动重定向，导致返回值不一样。弃用。同时这个方法返回的响应值头需要自己组装。
		// resp, err := client.Do(req)
		// client := &http.Client{
		// 	CheckRedirect: func(req *http.Request, via []*http.Request) error {
		// 		// 不允许自动重定向
		// 		return errUseLastResponse{}
		// 	},
		// }
		// 	if resp.StatusCode >= 301 && resp.StatusCode <= 308 {
		// 		// 处理重定向，例如记录日志、修改请求或转发重定向响应
		// 		location := resp.Header.Get("Location")
		// 		log.Printf("Redirect to: %s", location)
		// 	}
		// 	// fmt.Println("status=", resp.Status)
		// 	statusLine := fmt.Sprintf("HTTP/1.1 %s\r\n", resp.Status)
		// 	io.WriteString(clientConn, statusLine)
		// 	// 将响应转发给客户端
		// 	headerKeys := []string{
		// 		"Accept-Ranges",
		// 		"Age",
		// 		"Cache-Control",
		// 		"Content-Type",
		// 		"Date",
		// 		"Etag",
		// 		"Expires",
		// 		"Last-Modified",
		// 		"Server",
		// 		"Vary",
		// 		"X-Cache",
		// 		"Content-Length",
		// 		"Connection",
		// 	}

		// 	// 遍历头部键的顺序并发送每个头部
		// 	for _, key := range headerKeys {
		// 		if values, ok := resp.Header[key]; ok {
		// 			for _, value := range values {
		// 				headerLine := fmt.Sprintf("%s: %s\r\n", key, value)
		// 				io.WriteString(clientConn, headerLine)
		// 			}
		// 		}
		// 	}

		// 	io.WriteString(clientConn, "\r\n")

		// 	if resp.Body != nil {
		// 		io.Copy(clientConn, resp.Body)
		// 	}
	}
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: http_proxy <port>")
		os.Exit(1)
	}

	port := ":" + os.Args[1] //端口
	l, err := net.Listen("tcp", port)
	if err != nil {
		fmt.Println("Error listening:", err)
		return
	}
	// defer l.Close()
	fmt.Println("Listening on :" + os.Args[1])

	for {
		// 接受连接
		clientConn, err := l.Accept()
		if err != nil {
			fmt.Println("Error accepting:", err)
			continue
		}
		// fmt.Println("Connection accepted")

		// 并发处理每个请求
		go handleRequest(clientConn)
	}
}
